package com.lynn.common.utils.date;

import android.text.TextUtils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * DESC: 时间工具类
 * TIME:2019-06-24
 */
public class DateTimeUtil {
    public static final String STANDARD_TIME = "yyyy-MM-dd HH:mm:ss";
    public static final String FULL_TIME = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String YEAR_MONTH_DAY = "yyyy-MM-dd";
    public static final String YEAR_MONTH_DAY_CN = "yyyy年MM月dd号";
    public static final String HOUR_MINUTE_SECOND = "HH:mm:ss";
    public static final String HOUR_MINUTE_SECOND_CN = "HH时mm分ss秒";
    public static final String YEAR = "yyyy";
    public static final String MONTH = "MM";
    public static final String DAY = "dd";
    public static final String HOUR = "HH";
    public static final String MINUTE = "mm";
    public static final String SECOND = "ss";
    public static final String MILLISECOND = "SSS";
    public static final String YESTERDAY = "昨天";
    public static final String TODAY = "今天";
    public static final String TOMORROW = "明天";
    public static final String SUNDAY = "星期日";
    public static final String MONDAY = "星期一";
    public static final String TUESDAY = "星期二";
    public static final String WEDNESDAY = "星期三";
    public static final String THURSDAY = "星期四";
    public static final String FRIDAY = "星期五";
    public static final String SATURDAY = "星期六";
    public static final String[] weekDays = {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};

    private DateTimeUtil() {}

///////////////////////////////////////////////////////////////////////////
// DATE
///////////////////////////////////////////////////////////////////////////

    /**
     * 获取标准时间
     *
     * @return 例如 2021-07-01 10:35:53
     */
    public static String getDateTime() {
        return new SimpleDateFormat(STANDARD_TIME, Locale.CHINESE).format(new Date());
    }


    /**
     * 判断原日期是否在目标日期之前
     */
    public static boolean isBefore(Date src, Date dst) {
        return src.before(dst);
    }

    /**
     * 判断原日期是否在目标日期之后
     */
    public static boolean isAfter(Date src, Date dst) {
        return src.after(dst);
    }

    /**
     * 判断两日期是否相同
     */
    public static boolean isEqual(Date date1, Date date2) {
        return date1.compareTo(date2) == 0;
    }

    /**
     * 判断某个日期是否在某个日期范围
     *
     * @param beginDate 日期范围开始
     * @param endDate   日期范围结束
     * @param src       需要判断的日期
     */
    public static boolean between(Date beginDate, Date endDate, Date src) {
        return beginDate.before(src) && endDate.after(src);
    }


    /**
     * 一种时间格式转化成另一种时间格式
     *
     * @param srcDate   原日期格式字符串
     * @param srcFormat 原格式
     * @param objFormat 目标格式
     * @return 目标格式字符串
     */
    public static String convert(String srcDate, String srcFormat, String objFormat) {
        long time = parse2MilliSec(srcDate, srcFormat);
        return formatMilliSec(time, objFormat);
    }


    /**
     * 获得当前时间的<code>java.util.Date</code>对象
     * now().getTime() = {@link #nowMilliSec() }
     */
    public static Date now() {
        return new Date();
    }

    /**
     * 返回当前unix时间戳 (1970年至今的 秒数)
     */
    public static long nowSec() {
        return nowMilliSec() / 1000;
    }

    /**
     * 返回当前unix时间戳 (1970年至今的 毫秒数)
     */
    public static long nowMilliSec() {
        return System.currentTimeMillis();
    }

    /**
     * 得到今天的日期字符串
     */
    public static String nowDateStr(String format) {
        return format(now(), format);
    }

    /**
     * 给定日历对象 获取对应的日期对象
     *
     * @param c Calendar 对象
     * @return Date 对象
     */
    public Date getDate(Calendar c) {
        if (c == null) {
            return now();
        }
        return c.getTime();
    }


///////////////////////////////////////////////////////////////////////////
// DATE :
//       时间字符串 <=> date
///////////////////////////////////////////////////////////////////////////


    public static long parse2Sec(String dateStr, String format) {
        return parse2MilliSec(dateStr, format) / 1000;
    }


    public static long parse2MilliSec(String dateStr, String format) {
        if (TextUtils.isEmpty(dateStr)) {
            return 0;
        }
        Date date = parse(dateStr, format);
        if (date != null)
            return date.getTime();
        return 0;
    }


    /**
     * @param dateStr 需要转化的日期字符串
     * @param format  日期格式
     */
    public static Date parse(String dateStr, String format) {
        if (TextUtils.isEmpty(dateStr)) {
            return null;
        }
        Date date = null;
        try {
            date = getSDF(format).parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }


    public static String formatSec(String timeStamp, String format) {
        long time = convert2Long(timeStamp, 0L);
        return formatSec(time, format);
    }


    public static String formatSec(long timeStamp, String format) {
        return formatMilliSec(timeStamp * 1000, format);
    }


    public static String formatMilliSec(String timeStamp, String format) {
        long time = convert2Long(timeStamp, 0L);
        return formatMilliSec(time, format);
    }


    public static String formatMilliSec(long timeStamp, String format) {
        if (timeStamp == 0) return "";
        return format(new Date(timeStamp), format);
    }


    public static String format(Date d, String format) {
        if (d == null) {
            return "";
        }
        return getSDF(format).format(d);
    }


    public static SimpleDateFormat getSDF(String format) {
        if (TextUtils.isEmpty(format)){
            format = "yyyy-MM-dd HH:mm:ss";
        }
        return new SimpleDateFormat(format, Locale.CHINA);
    }

///////////////////////////////////////////////////////////////////////////
// Calendar日期处理类: 用来处理日期的设值，获取相应的年，月，日。
// 通过传入Date对象，获取想要的相关数据，或者获得用Calendar处理后，想要的数据
//
// GregorianCalendar是Calendar的一个具体子类，提供了世界上大多数国家/地区使用的标准日历系统。
//
// 月份：一月是0，二月是1，以此类推，12月是11
// 星期：周日是1，周一是2，。。。。。周六是7
///////////////////////////////////////////////////////////////////////////

    /**
     * 获取默认的日历对象
     * 使用目前的时区和语言环境的方法得到一个日历
     */
    private static Calendar getCalendar() {
        return Calendar.getInstance();
    }

    /**
     * 给定日期，返回日历对象
     *
     * @param date 日期对象
     */
    public static Calendar getCalendar(Date date) {
        Calendar c = getCalendar();
        if (date != null) {
            c.setTime(date);
        }
        return c;
    }

    /**
     * 获取给定日历对象中的 年月日时分秒等属性
     *
     * @param c     日历对象
     * @param field 属性type   Calendar.YEAR， Calendar.MONTH，(Calendar.DAY_OF_MONTH = Calendar.DATE)
     *              Calendar.HOUR_OF_DAY,Calendar.MINUTE,Calendar.SECOND
     * @return 属性type的值
     */
    public static int getFieldValue(Calendar c, int field) {
        if (c == null) c = getCalendar();
        switch (field) {
            case Calendar.MONTH:
                return c.get(field) + 1;
        }
        return c.get(field);
    }


    /**
     * 周日是1，周一是2，。。。。。周六是7
     */
    public static int getWeekDayValue(Calendar c) {
        return getFieldValue(c, Calendar.DAY_OF_WEEK);
    }

    public static int getCurWeekDayValue() {
        return getWeekDayValue(null);
    }

    /**
     * 获得当前周weekDay对应的日期
     * 注：US等每星期第一天为sunday
     *
     * @param week Calendar.SUNDAY ~ Calendar.SATURDAY
     * @return Date 对象
     */
    public static Date getWeekDayDate(int week) {
        Calendar c = getCalendar();
        c.set(Calendar.DAY_OF_WEEK, week);
        return c.getTime();
    }


    /**
     * 获得相对今天的位移天数的日期
     *
     * @param offDay 位移天数 -1 昨天 1 明天
     */
    public static Date getOffDayDate(int offDay) {
        Calendar c = getCalendar();
        c.add(Calendar.DATE, offDay);
        return c.getTime();
    }


    /**
     * @param c     Calendar 对象
     * @param field field
     * @return 最大值
     */
    public static int getMaxValue(Calendar c, int field) {
        if (c == null) c = getCalendar();
        return c.getActualMaximum(field);
    }


    /**
     * @param c     Calendar 对象
     * @param field field
     * @return 最小值
     */
    public static int getMinValue(Calendar c, int field) {
        if (c == null) c = getCalendar();
        return c.getActualMinimum(field);
    }


    /**
     * 获得相对当前月 位移月的日期
     *
     * @param offMon 位移月数
     * @return Calendar 对象
     */
    private static Calendar getOffMonth(int offMon) {
        Calendar c = getCalendar();
        c.add(Calendar.MONTH, offMon);
        return c;
    }

    /**
     * 获得相对当前月 位移月的日期
     *
     * @param offMon 位移月数
     * @return Date 对象
     */
    public static Date getOffMonthDate(int offMon) {
        Calendar c = getOffMonth(offMon);
        return c.getTime();
    }


    /**
     * 获取相对于当月 月份中第几天的日期
     *
     * @param offMonth   位移月数 0 当月，-1 上个月 1下个月 以此类推
     * @param dayOfMonth 第几天 1 第一天
     * @return Date 对象
     */
    public static Date getDayOfMonthDate(int offMonth, int dayOfMonth) {
        Calendar c = getOffMonth(offMonth);
        int days = getMaxValue(c, Calendar.DAY_OF_MONTH);
        if (dayOfMonth > 0 && dayOfMonth <= days) {
            c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        } else {
            //否则设置成第一天
            c.set(Calendar.DAY_OF_MONTH, 1);
        }
        return c.getTime();
    }

    /**
     * 将对象转化为long，如果不符合要求返回默认值,防止value为""或者null
     */
    public static long convert2Long(Object value, long defaultValue) {
        if (value == null || "".equals(value.toString().trim())) {
            return defaultValue;
        }
        try {
            return Long.valueOf(value.toString());
        } catch (NumberFormatException e) {
            try {
                return Double.valueOf(value.toString()).longValue();
            } catch (NumberFormatException e1) {
                return defaultValue;
            }
        }
    }

///////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////

    /**
     * 获取起止日期
     *
     * @param format 需要显示的日期格式
     * @param date   需要参照的日期
     * @param n      最近n周
     * @param option 0 开始日期；1 结束日期
     * @param k      0 包含本周 1 不包含本周
     * @return
     */
    public static String getFromToDate(String format, Date date, int n, int option, int k) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) /*- 1*/;
        int offset = 0 == option ? 1 - dayOfWeek : 7 - dayOfWeek;
        int amount = 0 == option ? offset - (n - 1 + k) * 7 : offset - k * 7;
        calendar.add(Calendar.DATE, amount);
        return getSDF(format).format(calendar.getTime());
    }

    /**
     * 根据当前日期获得最近n周的日期区间（包含本周）
     */
    public static String getNWeekTimeInterval(int n, String format) {
        String beginDate = getFromToDate(format, new Date(), n, 0, 0);
        String endDate = getFromToDate(format, new Date(), n, 1, 0);
        return beginDate + "," + endDate;
    }

    /**
     * 根据当前日期获得最近n周的日期区间（不包含本周）
     */
    public static String getNWeekTimeIntervalTwo(int n, String format) {
        String beginDate = getFromToDate(format, new Date(), n, 0, 1);
        String endDate = getFromToDate(format, new Date(), n, 1, 1);
        return beginDate + "," + endDate;
    }

    /**
     * 根据当前日期获得本周的日期区间（本周周一和周日日期）
     */
    public static String getThisWeekTimeInterval(String format) {
        return getNWeekTimeInterval(1, format);
    }

    /**
     * 根据当前日期获得上周的日期区间（上周周一和周日日期）
     */
    public static String getLastWeekTimeInterval(String format) {
        return getNWeekTimeIntervalTwo(1, format);
    }

}
